package com.k2data.k2app.controller;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.k2data.k2app.constant.Constant;
import com.k2data.k2app.domain.DeviceCond;
import com.k2data.k2app.domain.DeviceDTO;
import com.k2data.k2app.domain.EventCond;
import com.k2data.k2app.domain.po.Customer;
import com.k2data.k2app.domain.po.EventCustomer;
import com.k2data.k2app.domain.po.v1.Event;
import com.k2data.k2app.mapper.EventCustomerMapper;
import com.k2data.k2app.mapper.EventMapper;
import com.k2data.k2app.response.CommonResultResponse;
import com.k2data.k2app.response.PageInfo;
import com.k2data.k2app.response.ResponseHelper;
import com.k2data.k2app.rest.SysClient;
import com.k2data.k2app.rest.domain.RectList;
import com.k2data.k2app.service.CustomerService;
import com.k2data.k2app.service.DeviceService;
import com.k2data.k2app.service.SusbTimeIndexService;
import com.k2data.k2app.utils.HanyuPinyinHelper;
import com.k2data.k2app.utils.StringUtils;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.text.Collator;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lidong9144@163.com 17-3-17.
 */
@RestController
@RequestMapping("/customers")
public class CustomerController {
    @Autowired
    private SysClient sysClient;
    @Autowired
    private SusbTimeIndexService susbTimeIndexService;

    private final static Comparator<Object> CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA);
    private final EventCustomerMapper eventCustomerMapper;
    private final DeviceService deviceService;
    private final CustomerService customerService;
    private final EventMapper eventMapper;

    @Autowired
    public CustomerController(EventCustomerMapper eventCustomerMapper, DeviceService deviceService,
                              CustomerService customerService, EventMapper eventFaultMapper) {
        this.eventCustomerMapper = eventCustomerMapper;
        this.deviceService = deviceService;
        this.customerService = customerService;
        this.eventMapper = eventFaultMapper;
    }

    @ApiOperation(value = "添加")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "customer", value = "customer", required = true, dataType = "Customer", paramType = "body")
    })
    @PostMapping(value = "", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CommonResultResponse> post(@Valid @RequestBody Customer customer) throws Exception {
        return ResponseHelper.success(customerService.insert(customer));
    }

    @ApiOperation(value = "更新")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true, dataType = "Long", paramType = "path"),
            @ApiImplicitParam(name = "customer", value = "customer", required = true, dataType = "Customer", paramType = "body")
    })
    @PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<CommonResultResponse> put(@PathVariable("id") Long id, @RequestBody Customer customer) throws Exception {
        customer.setId(id);

        return ResponseHelper.success(customerService.update(customer));
    }

    @ApiOperation(value = "删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true, dataType = "Long", paramType = "path")
    })
    @DeleteMapping(value = "/{id}")
    public ResponseEntity<CommonResultResponse> delete(@PathVariable("id") Long id) throws Exception {
        return ResponseHelper.success(customerService.delete(id));
    }

    @ApiOperation(value = "获取客户对应的设备")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "customerId", required = true, dataType = "Long", paramType = "path"),
            @ApiImplicitParam(name = "withBoms", value = "是否关联查询部件", dataType = "boolean", paramType = "query")
    })
    @GetMapping(value = "/{id}/devices")
    public ResponseEntity<CommonResultResponse> getDevice(@PathVariable("id") Long id,
                                                          @RequestParam(value = "withBoms", required = false) boolean withBoms
    ) throws Exception {
        DeviceCond cond = new DeviceCond();
        cond.setCustomerId(id);
        cond.setIsRoot(Constant.YES);

        List<DeviceDTO> deviceDTOs = deviceService.selectDeviceByCustomer(cond);
        deviceDTOs.forEach(s->{
            s.setParentId(0L);
            s.setRootId(s.getId());
        });
        if(withBoms) {
            for (int i = 0; i < deviceDTOs.size() ; i++) {
                List<DeviceDTO> deviceDTOs1 = deviceService.selectDeviceBomDeep(deviceDTOs.get(i).getId());
                if(deviceDTOs1.size()>0){
                    deviceDTOs.get(i).setChildren(deviceDTOs1.get(0).getChildren());
                }
            }
        }
        return ResponseHelper.success(deviceDTOs);
    }

    @ApiOperation(value = "获取客户对应的文件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "customerId", required = true, dataType = "Long", paramType = "path")
    })
    @GetMapping(value = "/{id}/files")
    public ResponseEntity<CommonResultResponse> getFiles(@PathVariable("id") Long id) throws Exception {
        return ResponseHelper.success(customerService.getFileUrls(id));
    }

    @ApiOperation(value = "获取客户联系人")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "customerId", required = true, dataType = "Long", paramType = "path")
    })
    @GetMapping(value = "/{id}/contacts")
    public ResponseEntity<CommonResultResponse> getContacts(@PathVariable("id") Long id) throws Exception {
        return ResponseHelper.success(customerService.getContactsByCustomer(id));
    }

    @ApiOperation(value = "获取客户所有联系人")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "customerId", required = true, dataType = "Long", paramType = "path")
    })
    @GetMapping(value = "/{id}/contacts/all")
    public ResponseEntity<CommonResultResponse> getContactsAll(@PathVariable("id") Long id) throws Exception {
        return ResponseHelper.success(customerService.getContactsByCustomerAll(id));
    }


    @ApiOperation(value = "获取客户事件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "customerId", required = true, dataType = "Long", paramType = "path")
    })
    @GetMapping(value = "/{id}/events")
    public ResponseEntity<CommonResultResponse> getEvent(@PathVariable("id") Long id) throws Exception {
        EventCond cond = new EventCond();
        cond.setCustomerId(id);

        return ResponseHelper.success(eventCustomerMapper.selectList(cond));
    }

    @ApiOperation(value = "获取客户分组")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "date", value = "日期", dataType = "Date", paramType = "query"),
            @ApiImplicitParam(name = "location", value = "地域", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "industry", value = "行业", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "customerType", value = "客户类型", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "dataSource", value = "数据来源", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "owner", value = "负责人", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "status", value = "状态", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "userId", value = "当前登陆用户", dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "customerNo", value = "编号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "customerId", value = "客户id", dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "orderBy", value = "orderBy", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "orderType", value = "倒叙还是正序，默认正序", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "name", value = "name", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "withPinYin", value = "带拼音信息", dataType = "Boolean", paramType = "query"),
    })
    @GetMapping(value = "")
    public ResponseEntity<CommonResultResponse> getDeviceGroupList(
            @RequestParam(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
            @RequestParam(value = "location", required = false) String location,
            @RequestParam(value = "industry", required = false) String industry,
            @RequestParam(value = "customerType", required = false) String customerType,
            @RequestParam(value = "dataSource", required = false) String dataSource,
            @RequestParam(value = "owner", required = false) String owner,
            @RequestParam(value = "status", required = false) String status,
            @RequestParam(value = "userId", required = false) Long userId,
            @RequestParam(value = "customerNo", required = false) String customerNo,
            @RequestParam(value = "customerId", required = false) Long customerId,
            @RequestParam(value = "pageNum", required = false) Integer pageNum,
            @RequestParam(value = "pageSize", required = false) Integer pageSize,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam(value = "orderBy", required = false) String orderBy,
            @RequestParam(value = "orderType", required = false) String orderType,
            @RequestParam(value = "withPinYin", required = false) Boolean withPinYin
    ) throws Exception {
        DeviceCond cond = new DeviceCond();

        if (date != null) {
            cond.setStartDate(date);
            cond.setEndDate(date.plusDays(1));
        }

        cond.setLocation(location);
        cond.setIndustry(industry);
        cond.setCustomerType(customerType);
        cond.setDataSource(dataSource);
        cond.setOwner(owner);
        cond.setCustomerNo(customerNo);
        cond.setCustomerName(name);
        cond.setCustomerId(customerId);
        cond.setUserId(userId);
        cond.setStatus(status);
        if(!StringUtils.isEmpty(orderBy)){
            cond.setOrderBy(orderBy);
        }else {
            cond.setOrderBy("customer_no");
        }
        if(StringUtils.isEmpty(orderType)){
            cond.setOrderType(orderType);
        }


        int pageNumReal = pageNum == null ? 1 : pageNum;
        int pageSizeReal = pageSize == null ? Constant.DEFAULT_PAGE_SIZE : pageSize;

        List<DeviceDTO> list = customerService.getDeviceCustomers(cond);
        // 名称按照中文排序
        if(!StringUtils.isEmpty(orderBy) && orderBy.equals("name")){
            list.sort((o1,o2) -> CHINA_COMPARE.compare(o1.getName(),o2.getName()));
        }

        if(!StringUtils.isEmpty(orderBy)){
            cond.setOrderBy(orderBy);
        }else {
            cond.setOrderBy("customer_no");
        }
        int count = list.size();
        PageInfo pageInfo = new PageInfo(pageNumReal, pageSizeReal, count);

        int fromIndex = (pageNumReal - 1) * pageSizeReal;
        if (fromIndex > count) {
            fromIndex = count;
        }
        int toIndex = pageNumReal * pageSizeReal;
        if (toIndex > count) {
            toIndex = count;
        }
        List<DeviceDTO> deviceDTOs = list.subList(fromIndex, toIndex);
        // 是否返回客户名带拼音属性的结果
        if(withPinYin != null && withPinYin){
            deviceDTOs.forEach(i->{
                HanyuPinyinHelper hanyuPinyinHelper = new HanyuPinyinHelper();
                i.setPinyin(hanyuPinyinHelper.toHanyuPinyin(i.getName()));
                i.setPy(HanyuPinyinHelper.getFirstLettersLo(i.getName()));
                i.setPyFirst(HanyuPinyinHelper.getFirstLetter(i.getName()));
                System.out.println();
            });
            Map<String, List<DeviceDTO>> collect = deviceDTOs.stream().collect(Collectors.groupingBy(DeviceDTO::getPyFirst));
            Map<String,List<DeviceDTO>> xMap=new LinkedHashMap<>();
            collect.entrySet().stream().sorted(Map.Entry.<String,List<DeviceDTO>>comparingByKey()) //reversed不生效
                    .forEachOrdered(x->xMap.put(x.getKey(),x.getValue()));
            List<DeviceDTO> resultSort = new ArrayList<>();
            xMap.forEach((i,k)->{
                resultSort.add(new DeviceDTO(i,i.toLowerCase(),i.toLowerCase()));
                resultSort.addAll(k);
            });
            return ResponseHelper.success(resultSort, pageInfo);
        }
        return ResponseHelper.success(deviceDTOs, pageInfo);
    }

    @ApiOperation(value = "获取客户分组")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true, dataType = "Long", paramType = "path")
    })
    @GetMapping(value = "/{id}")
    public ResponseEntity<CommonResultResponse> getDeviceCustomer(
            @PathVariable("id") Long id,
            @RequestParam(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date
    ) throws Exception {
        DeviceCond cond = new DeviceCond();

        if (date != null) {
            cond.setStartDate(date);
            cond.setEndDate(date.plusDays(1));
        }

        cond.setCustomerId(id);

        List<DeviceDTO> list = customerService.getDeviceCustomers(cond);

        if (list.isEmpty()) {
            return ResponseHelper.success(Maps.newHashMap());
        }

        return ResponseHelper.success(list.get(0));
    }

    @ApiOperation(value = "故障列表")
    @GetMapping(value = "/faults")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "faultLimit", value = "前几条", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "faultType", value = "故障类型", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "userId", value = "当前登陆用户id(userId)", dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "customerId", value = "客户id", dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "startDateTime", value = "开始时间", dataType = "date", paramType = "query"),
            @ApiImplicitParam(name = "endDateTime", value = "结束时间", dataType = "date", paramType = "query")
    })
    public ResponseEntity<CommonResultResponse> getFaultList(
            @RequestParam(value = "faultLimit", required = false) Integer faultLimit,
            @RequestParam(value = "faultType", required = false) String faultType,
            @RequestParam(value = "userId", required = false) Long userId,
            @RequestParam(value = "customerId", required = false) Long customerId,
            @RequestParam(value = "startDateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime startDateTime,
            @RequestParam(value = "endDateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) ZonedDateTime endDateTime
    ) throws Exception {
        DeviceCond cond = new DeviceCond();
        cond.setStartDateTime(startDateTime);
        cond.setEndDateTime(endDateTime);
        cond.setCustomerId(customerId);

        if(userId!=null && !"".equals(userId)){
            // 权限过滤，管理员不加权限过滤功能，默认所有权限
            RectList rolesByUser = sysClient.getRolesByUser(userId);
            List list = rolesByUser.getResult();
            if(list!=null && list.size()>0){
                Map map = (Map)list.get(0);
                if(map.get("enname")!=null && !map.get("enname").toString().equals("Administrator")){
                    cond.setUserId(userId);
                }
            }else{
                //用户没有角色，所以也不是管理员，关联查询
                cond.setUserId(userId);
            }
        }

        // 构造类型查询条件
        List<String> faultTypeCond = Lists.newArrayList();
        if (!StringUtils.isBlank(faultType)) {
            faultTypeCond.add(faultType);
        } else if (faultLimit != null) {
            List<Event> typeCount = eventMapper.selectTypeCount(null);

            if (faultLimit < typeCount.size()) {
                typeCount.sort(Comparator.comparingInt(Event::getCount));
                typeCount = typeCount.subList(typeCount.size() - faultLimit, typeCount.size());
            }

            for (Event eventFault : typeCount) {
                faultTypeCond.add(eventFault.getEventType());
            }
        }
        cond.setFaultTypes(faultTypeCond);

        return ResponseHelper.success(customerService.selectCustomerFault(cond));
    }

    @ApiOperation(value = "设备")
    @GetMapping(value = "/devices")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "groupby", value = "groupby", required = true, dataType = "string", paramType = "query")
    })
    public ResponseEntity<CommonResultResponse> getFaultList(
            @RequestParam(value = "groupby") String groupby
    ) throws Exception {

        return ResponseHelper.success(customerService.getAllDevices(groupby));
    }


    @ApiOperation(value = "获取客户开机时长")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true, dataType = "Long", paramType = "path"),
            @ApiImplicitParam(name = "years", value = "年份", allowMultiple = true, dataType = "string", paramType = "query"),
    })
    @GetMapping(value = "/{id}/susb")
    public ResponseEntity<CommonResultResponse> getSusbIndexTime(
            @PathVariable("id") Long id,
            @RequestParam(value = "years", required = false) List<String> years
    ) throws Exception {
        if(years == null || years.size() == 0){
            Integer year = LocalDate.now().getYear();
            years = Arrays.asList(String.valueOf(year));
        }
        Map<Integer, Map<Integer, Map>> datas = Maps.newHashMap();
        Map<Integer, Map<Integer, Map>> integerMapMap = susbTimeIndexService.selectSusbGroupYear(id, null,years);
        years.forEach(s->{
            datas.put(Integer.parseInt(s),integerMapMap.get(Integer.parseInt(s)));
        });
        return ResponseHelper.success(datas);
    }

    @ApiOperation(value = "获取客户发生事件类型及个数")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "id", required = true, dataType = "Long", paramType = "path"),
            @ApiImplicitParam(name = "year", value = "年份", dataType = "string", paramType = "query"),
    })
    @GetMapping(value = "/{id}/eventcount")
    public ResponseEntity<CommonResultResponse> getCustomerEventCount(
            @PathVariable("id") Long id,
            @RequestParam(value = "year", required = false) String year
    ) throws Exception {
        if(year == null){
            year = String.valueOf(LocalDate.now().getYear());
        }
        EventCond cond=new EventCond();
        cond.setCustomerId(id);
        cond.setNowyear(year);
        List<EventCustomer> eventCustomers =eventCustomerMapper.selectTypeCountNowYear(cond);
        List<String> months=Lists.newArrayList();
        Map<String, List<EventCustomer>> datas = Maps.newHashMap();
        //List<EventCustomer> mapList=Lists.newArrayList();
        for (EventCustomer eventCustomer:eventCustomers) {
            months.add(eventCustomer.getMonth());
        }
        months.forEach(s->{
            datas.put(s,Lists.newArrayList());
        });
        for (EventCustomer eventCustomer:eventCustomers) {
            datas.get(eventCustomer.getMonth()).add(eventCustomer);
        }

//        String[] countMonth=new String[12];
//        Map<EventCustomer,List<String>> eventMap=Maps.newHashMap();
//        List<EventCustomer> eventList=Lists.newArrayList();
//        for (EventCustomer eventCustomer:eventCustomers) {
//            eventList.add(eventCustomer);
//        }
//        eventList.forEach(s->{
//            eventMap.put(s,Lists.newArrayList());
//        });
//        for (EventCustomer eventCustomer:eventCustomers) {
//            eventMap.get(eventCustomer).add(eventCustomer.getCount().toString());
//        }

       // List<Map<String,Object>> reList=Lists.newArrayList();

//        for (EventCustomer eventCustomer:eventCustomers) {
//            Map<String, Object> reMap = Maps.newHashMap();
//            if (reMap.get("deviceId") == null&&reMap.get("deviceId")!=eventCustomer.getDeviceId()) {
//                reMap.put("deviceId", eventCustomer.getDeviceId());
//                reMap.put("type", eventCustomer.getType());
//                reMap.put("count", eventCustomer.getCount());
//                reMap.put("deviceName", eventCustomer.getDeviceName());
//            } else if(reMap.get("deviceId")==eventCustomer.getDeviceId()){
//                reMap.put("count", reMap.get("count").toString() + "," + eventCustomer.getCount());
//            }
//            reList.add(reMap);
//        }


        Map<Map<String,Object>, List<Integer>> resultMap = Maps.newHashMap();
        Set<Integer> yearList= Sets.newHashSet();//用来保存月份且不重复
        for (EventCustomer eventCustomer:eventCustomers) {
            yearList.add(Integer.parseInt(eventCustomer.getMonth()));
        }
        for (EventCustomer eventCustomer:eventCustomers) {
            Map<String,Object> map=Maps.newHashMap();
            map.put("deviceId", eventCustomer.getDeviceId());
            map.put("type", eventCustomer.getType());
            map.put("deviceName", eventCustomer.getDeviceName());
            if(resultMap.containsKey(map)){
                resultMap.get(map).set(Integer.parseInt(eventCustomer.getMonth())-1,eventCustomer.getCount());
            }else{
                List<Integer> list=new ArrayList<Integer>();
                for(int i=0;i<=12;i++){
                    list.add(null);
                }
                list.set(Integer.parseInt(eventCustomer.getMonth())-1,eventCustomer.getCount());
                resultMap.put(map,list);
            }
        }

        List<Map<String,Object>> reList=Lists.newArrayList();
        for (EventCustomer eventCustomer:eventCustomers) {
            Map<String,Object> map=Maps.newHashMap();
            map.put("deviceId", eventCustomer.getDeviceId());
            map.put("type", eventCustomer.getType());
            map.put("deviceName", eventCustomer.getDeviceName());
            //去除countList中的null值
            List<Integer> list=resultMap.get(map);
            List<Integer> countList=Lists.newArrayList();
            for (Integer month:yearList) {
                countList.add(list.get(month-1));
            }
            map.put("count",countList);
            reList.add(map);
        }
        Map<String,Object> reMap=Maps.newHashMap();
        reMap.put("month",yearList);
        reMap.put("data",removeDuplicate(reList));
        return ResponseHelper.success(reMap);
    }

    //list根据元素中的内容去重
    private static ArrayList<Map<String,Object>> removeDuplicate(List<Map<String,Object>> mapList) {
        Set<Map<String,Object>> set = new TreeSet<Map<String,Object>>(new Comparator<Map<String,Object>>() {
            @Override
            public int compare(Map<String,Object> o1, Map<String,Object> o2) {
                //字符串,则按照asicc码升序排列
                return (o1.get("deviceId").toString()+o1.get("type").toString()).compareTo(o2.get("deviceId").toString()+o2.get("type").toString());
            }
        });
        set.addAll(mapList);
        return new ArrayList<Map<String,Object>>(set);
    }


    @ApiOperation(value = "故障事件类型数量")
    @GetMapping(value = "/industrys/count")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "userId", required = false, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "showType", value = "allStatus:全部状态 onlySelf:有状态的显示", dataType = "String", paramType = "query")
    })
    public ResponseEntity<CommonResultResponse> getFaultCount(
            @RequestParam(value = "userId", required = false) Long userId,
            @RequestParam(value = "showType", required = false) String showType
    ) throws Exception {
        DeviceCond cond = new DeviceCond();
        showType=showType==null?"allStatus":showType;
        cond.setUserId(userId);
        return ResponseHelper.success(customerService.getIndustryCount(cond,showType));
    }

}
